#ifndef GAMEENGINE_MAPS_TERRAIN_DESCRIPTOR_H
#define GAMEENGINE_MAPS_TERRAIN_DESCRIPTOR_H

#include <GameEngine/Maps/maps_settings.h>

#include <GameEngine/Maps/displacement.h>

#include <map>



#ifdef GAMEENGINE_NAMESPACES
namespace GameEngine {
#endif

//=================================================================================


//! Description of the behavior of a specific terrain
/*!
 *  A terrain descriptor contains the list of displacement types that are allowed on the specific
 *  terrain (walk, fly, swim) and the speed associated to these types of displacements
 */
class _Maps_decl TerrainDescriptor {

public:
	//! Enumerates which type of terrain a cell can belong to
	enum TerrainType {
		Grass,
		Desert,

		// Forest types
		Forest,
		Clearing,
		RainForest,

		// Urban environment
		TownSquare,
		Park,
		House,
		Path,
		Road,
		PavedRoad,
		Highway,
		Avenue,
		Street,
		Wall,

		// Seafront / lakes
		Sand,
		Sea,
		Ocean,
		Lake,
		Pond,
		River,
		Lagoon,
		Water,

		// Swamps
		Swamp,
		Mud,

		// Mountains
		Rocks,
		Mountain,
		Cliff,
		Ice,
		Snow,
		Volcano,
		Lava,

		// Number of terrain types
		InvalidTerrain
	};

	TerrainDescriptor();
	TerrainDescriptor(const TerrainDescriptor& rhs);
	TerrainDescriptor& operator=(const TerrainDescriptor& rhs);
	virtual ~TerrainDescriptor();

	const Displacement::DisplacementTypes& displacement_types() const;

	bool add_displacement_type(Displacement::DisplacementType displacement_type);
	bool remove_displacement_type(Displacement::DisplacementType displacement_type);
	bool has_displacement_type(Displacement::DisplacementType displacement_type) const;

	void set_speed(Displacement::DisplacementType displacement_type, float speed = 1);
	float speed(Displacement::DisplacementType displacement_type) const;
	float speed(Displacement::DisplacementTypes displacement_type) const;

protected:
	//! Describe which units can move on this cell
	Displacement::DisplacementTypes displacement_types_;

	//! Associate speed to the displacement types
	float speeds_[DisplacementTypeCount];
};

//=================================================================================


//! A list of terrain descriptions
/*!
 *  The terrain manager maps terrain types to their actual properties (i.e., allowed types of
 *  displacement and speed of displacement).
 *
 *  If asked for a terrain type that does not exist in the list of terrains associated to the
 *  terrain manager, the default type of terrain is returned.
 */
class _Maps_decl TerrainManager {

public:
	TerrainManager();
	TerrainManager(const TerrainManager& rhs);
	TerrainManager& operator=(const TerrainManager& rhs);
	virtual ~TerrainManager();

	virtual bool add_terrain(TerrainDescriptor::TerrainType type, const TerrainDescriptor& terrain);
	virtual bool remove_terrain(TerrainDescriptor::TerrainType type);
	virtual bool find_terrain(TerrainDescriptor::TerrainType type) const;

	TerrainDescriptor& default_terrain();
	const TerrainDescriptor& default_terrain() const;

	const std::map<TerrainDescriptor::TerrainType, TerrainDescriptor>& terrains() const;
	const TerrainDescriptor& get_terrain(TerrainDescriptor::TerrainType type) const;

protected:
	//! Describe which units can move on this cell
	std::map<TerrainDescriptor::TerrainType, TerrainDescriptor> terrains_;

	//! Default terrain description if asked for a non-existing terrain
	TerrainDescriptor default_terrain_;
};

//========================================================

#ifdef GAMEENGINE_NAMESPACES
} // namespace GameEngine
#endif

#endif
